package storage

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"time"

	"github.com/google/uuid"
	"go.etcd.io/bbolt"
)

type ClipType string

const (
	TypeText   ClipType = "text"
	TypeImage  ClipType = "image"
	maxClips            = 1000 // 最大存储条目数
	bucketName          = "clips"
)

type ClipItem struct {
	ID        string    `json:"id"`
	Type      ClipType  `json:"type"`
	Content   string    `json:"content"`
	Timestamp time.Time `json:"timestamp"`
	Preview   string    `json:"preview"` // 预览文本
	Size      int64     `json:"size"`    // 内容大小
	Hash      string    `json:"hash"`    // 内容哈希
}

type Manager struct {
	db         *bbolt.DB
	bucketName []byte
}

func NewManager() (*Manager, error) {
	// 获取用户配置目录
	userConfigDir, err := os.UserConfigDir()
	if err != nil {
		return nil, err
	}

	// 创建应用数据目录
	dbDir := filepath.Join(userConfigDir, "ClipPaste")
	if err := os.MkdirAll(dbDir, 0755); err != nil {
		return nil, err
	}

	// 打开数据库文件
	dbPath := filepath.Join(dbDir, "clips.db")
	db, err := bbolt.Open(dbPath, 0600, &bbolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		return nil, err
	}

	// 创建 bucket
	bucketName := []byte("clips")
	err = db.Update(func(tx *bbolt.Tx) error {
		_, err := tx.CreateBucketIfNotExists(bucketName)
		return err
	})
	if err != nil {
		db.Close()
		return nil, err
	}

	return &Manager{
		db:         db,
		bucketName: bucketName,
	}, nil
}

func (m *Manager) SaveClip(clip *ClipItem) error {
	if m.db == nil {
		return fmt.Errorf("database not initialized")
	}

	return m.db.Update(func(tx *bbolt.Tx) error {
		b := tx.Bucket(m.bucketName)
		if b == nil {
			return fmt.Errorf("bucket not found")
		}

		// 生成唯一ID
		if clip.ID == "" {
			clip.ID = uuid.New().String()
		}

		// 序列化数据
		encoded, err := json.Marshal(clip)
		if err != nil {
			return err
		}

		return b.Put([]byte(clip.ID), encoded)
	})
}

func (m *Manager) GetClips() ([]*ClipItem, error) {
	if m.db == nil {
		return nil, fmt.Errorf("database not initialized")
	}

	var clips []*ClipItem
	err := m.db.View(func(tx *bbolt.Tx) error {
		b := tx.Bucket(m.bucketName)
		if b == nil {
			return fmt.Errorf("bucket not found")
		}

		return b.ForEach(func(k, v []byte) error {
			var clip ClipItem
			if err := json.Unmarshal(v, &clip); err != nil {
				return err
			}
			clips = append(clips, &clip)
			return nil
		})
	})

	return clips, err
}

func (m *Manager) Close() error {
	if m.db != nil {
		return m.db.Close()
	}
	return nil
}
